Project summary
In 1971 a reciprocal introduction was done between Pod Kopiste island
and Pod Mrcaru island in the the South Adriatic Sea. Ten individuals of
Podarcis siculus were relocated from Pod Kopiste to Pod Mrcaru,
and 10 individuals of Podarcis melisellensis were relocated
from Pod Mrcaru to Pod Kopiste. Both islands were inhibited only by the
source species at the time - P. siculus on Pod Kopiste and
P. melisellensis on Pod Mrcaru.
After ~35 years researchers came back to the islands and witnessed
drastic morphological changes between P. siculus on Pod
Kopiste, and P. siculus on Pod Mrcaru. To link the genomics
with the phenotypic observation we sequenced 47 individuals of P.
siculus from each island. This report presents the sequence
coverage for the whole genome and the mitoGenome, and basic exploratory
analyses.
In all the plots K (Orange) represents the Pod
Kopiste population (the source) and M (Blue) represents
to Pod Mrcaru population (the relocated population).
Data summary
Data quality
Coverage
Cov<- read_csv(here::here("data/coverage_summary_130120.csv")) %>%
filter(!is.na(sample_name)) %>%
mutate(real_sample = fct_inorder(real_sample))
ggplot(Cov,aes(real_sample,mean_coverage,fill=island))+
geom_col(position = "dodge")+
scale_fill_manual(values=c("#E69F00", "#56B4E9"))+
theme_bw()+
theme(axis.ticks.x=element_blank(),
legend.position = "bottom",
legend.text = element_text(size = 15),
legend.title = element_text(size = 15),
axis.text.x = element_text(angle=90, vjust = 0.5),
axis.text.y = element_text(size = 15),
strip.text.x = element_text(size = 15,face="bold"),
axis.title.x = element_text(size = 15),
axis.title.y = element_text(size = 15))+
labs(y = "Coverage (X)", x = "sample",fill = "Sample Island:")

Error rate

LD decay
knitr::include_graphics(here::here("plots/plot_popK_popM_ngsLD.pdf"),dpi = 300)
SFS plots
par(mfrow=c(1,2))
p_realSFS(data_path = "data/angsd/popK_NoIntrogres_noRelated_LargeScaf_noSex_withDepth_150921.saf.sfs",pop_name = "PopK",main = "PopK noIntrogressed individuals")
p_realSFS(data_path = "data/angsd/popM_NoIntorgres_LargeScaf_noSex_withhDepth_150921.saf.sfs",pop_name = "PopM",main = "PopM noIntrogressed individuals")

PCA
PCAngsd_prop_table(data_path = "data/PCA_All_snpPval_LargeScaf_noSex_beagle_withDepth_190321.cov")
| SD |
2.217522 |
1.059708 |
1.0498274 |
1.0400453 |
1.0311287 |
| Proportion |
0.056479 |
0.012898 |
0.0126586 |
0.0124238 |
0.0122117 |
| Cumulative |
0.056479 |
0.069377 |
0.0820356 |
0.0944594 |
0.1066711 |
pca.minmaf<- plot_PCAngsd(data_file = "data/PCA_All_snpPval_LargeScaf_noSex_beagle_withDepth_190321.cov",var_data = pop_data,var_names = c("user_id","island"),plot_cols = cols.ps,pc_to_plot = c("PC1","PC2"))+
xlab("PC1 (5.6%)")+
ylab("PC2 (1.3%)")
pca.minmaf+
geom_point(size = 4)

plotly::ggplotly(pca.minmaf)
###pdf("plots/pca_res_new.pdf")
###pca.minmaf+
### geom_point(size = 4)
###dev.off()
IBS tree
plot_ibsTree(data_file = "data/ibs_All_snpPval_LargeScaf_noSex_withDepth_190321.ibsMat",col.nam = pop_data$user_id,color = cols.ps,pop.data = pop_data,root = T)

Admixture
We ran admixture using NGSAdmix to analyse how many clusters can be
seen among the two populations, excluding the related individuals from
PopK. Presented here are results for K=2, K=3 and K=4. There is no
quantitative method of choosing the correct K. However, K=2 shows a
clear divission between the two populations. K=3 adds another admixture
(green) which might represent P. melisellensis, however, it
does not align with the results from ABBA-BABA (see bellow).
knitr::include_graphics(here::here("plots/pong_k2_4_admix.png"),dpi = 300)

ABBA-BABA
PS_Pmelis_ref<- read_delim(here::here("data/abbababa_with_Pmlis_orig_jaknif.txt"),delim="\t",col_select = -10) %>%
#update the names to fit the names in the popdata file
mutate(H1 = str_extract(H1,"[^_]*_[^_]*"),H2 = str_extract(H2,"[^_]*_[^_]*"),H3 = str_extract(H3,"[^_]*_[^_]*"))
#create a vector that holds the islands
locIdx_PS<- pop_data2$island
#name it with the ind names that fit the abbababa data
names(locIdx_PS)<- pop_data2$ngi_id
#create a matrix that we will use to generate data for popK with popM as an outgroup in group
group_popK<- matrix(c(rep("K",2), "Pmelis"),ncol=3, byrow=T)
#run the function that renames all the file and keep only the rows that fit the fixed group setting
dstatFixH1H2PopKChangeH3 <- do.call(rbind,apply(group_popK, 1, getDstat3pop, dstatdf=PS_Pmelis_ref,locIdx = locIdx_PS))
leg_scale_popK<-max(c(abs(min(dstatFixH1H2PopKChangeH3$Z)),abs(max(dstatFixH1H2PopKChangeH3$Z))))
plot.PKPK<- plot.data.same.pop(dstatFixH1H2PopKChangeH3,title = "PopK H1, PopK H2, Pmelis H3, Pmur H4, PS ref")
plotly::ggplotly(plot.PKPK)
#create the same for popM
group_popM<- matrix(c(rep("M",2), "Pmelis"),ncol=3, byrow=T)
#do the same for popM as a set group
dstatFixH1H2PopMChangeH3 <- do.call(rbind,apply(group_popM, 1, getDstat3pop, dstatdf=PS_Pmelis_ref,locIdx = locIdx_PS))
leg_scale_popM<-max(c(abs(min(dstatFixH1H2PopMChangeH3$Z)),abs(max(dstatFixH1H2PopMChangeH3$Z))))
plot.PMPM<- plot.data(dstatFixH1H2PopMChangeH3,title = "PopM H1, PopM H2, Pmelis H3, Pmur H4, PS ref")
plotly::ggplotly(plot.PMPM)
Between population Fst
The Fst value between the two populations is
0.034475
Fst scans
Manhattan plot
fst_angsd<- read_delim(here::here("data/popK_popM_slidingWindow_fst_LargeScaf_noM48_nowhichfst_071221"),delim = "\t",col_names = F,skip = 1,col_select = -1) %>%
dplyr::rename(chr = X2,midpoint = X3, nsites = X4,PK_PM_fst = X5) %>%
mutate(cum_mid = cumsum(midpoint))
# calculate the threshold for outliers and the outliers
my_threshold.uw <- quantile(fst_angsd$PK_PM_fst, 0.995, na.rm = T)
fst_angsd_outlier<- fst_angsd %>%
mutate(outlier.uw = ifelse(PK_PM_fst > my_threshold.uw, "outlier", "background"))
outlier_table<- fst_angsd_outlier %>%
group_by(outlier.uw) %>%
tally()
knitr::kable(outlier_table,align = 'c')
| background |
255523 |
| outlier |
1285 |
# outlier plot
ggplot(fst_angsd_outlier,aes(cum_mid/10000000,PK_PM_fst,color = outlier.uw))+
geom_point(alpha = 0.75)+
theme_minimal()+
theme(legend.position = "none")+
scale_color_manual(values = c("#000000","#E4572E"))+
geom_hline(yintercept = my_threshold.uw,lty = 2)+
xlab("Gbp")+
ylab("Fst")

Fst peaks
chr.data<- read_delim(here::here("data/above_100kb_noSex_scaff_list.csv"),delim = ",")
fst_high<- fst_angsd_outlier$PK_PM_fst
true_peak<- fst_peaks(fst_high,limits = c(0.26,0.21))
knitr::kable(fst_angsd_outlier %>%
mutate(peak = case_when(PK_PM_fst%in%true_peak$fst_val~"peak",TRUE~"not_peak")) %>%
group_by(peak) %>%
tally())
fst_peak_plot<- fst_angsd_outlier %>%
mutate(peak = case_when(PK_PM_fst%in%true_peak$fst_val~"peak",TRUE~"not_peak")) %>%
ggplot(aes(cum_mid/10000000,PK_PM_fst,color = peak,size = peak))+
geom_point(alpha = 0.75)+
theme_minimal()+
theme(legend.position = "none")+
scale_color_manual(values = c("#000000","#960202"))+
geom_hline(yintercept = my_threshold.uw,lty = 2)+
xlab("Gbp")+
ylab("Fst")
####jpeg("plots/fst_peaks_plot2.jpeg",width = 40,height = 30,res = 200)
####fst_peak_plot
####dev.off()
BLAST results
Here are the three localities with the highest Fst between the
populations with the genes that area codes for and what this gene might
be related to.
knitr::kable(read_csv(here::here("data/forR_peaks_fst_outliers_RN_Method_091221_2.csv")) %>%
slice(1:3) %>%
select(4,10,11,12,13) %>%
rename(trans_id = lifted_clean.gff_res))
| 0.325397 |
XM_028723048.1 |
SIM1 |
downstream |
related to regulation of appetite and obesity |
| 0.322867 |
XM_028734363.1 |
SRGAP2 |
upstream |
Muscle function |
| 0.319335 |
XM_028729355.1 |
RHOBTB1 |
midpoint |
Muscle function |
Demographic modeling
The model that we focused on assumes that there is some introgression
from a ghost population in both of the populations that happened after
the bottleneck. This is the model we used:

The idea was to calculate the migration and population values that
are closest to the reality as we know it and let the optimization to
adjust the values to get the most likely model.
We checked whether the model gives a good estimation by comparing the
true Fst values with the modeled Fst values. This is
what we got:
| observed |
0.0357929 |
0.0413785 |
0.0347378 |
| modelled_C100 |
0.0393745 |
0.0449542 |
0.0303859 |
| modelled_C10 |
0.0359214 |
0.0414980 |
0.0287042 |
The new values were then used to generate SNPs from 100,000bp
simulated DNA fragments for each population. These SNPs were used to
calculate the 2dSFS. This was repeated 1,000 and compared to the true
Fst peak values we found in the Fst scan. This part is
giving some unexpected results and we are still in the process of
troubleshooting the problem.
Future planes
The plane now is to write the MS that will focus on our Fst scan
based genetic findings and the introgression. Once that is done, we plan
to work on the various museum samples that we have to see the change in
the genetic composition over time.
LS0tCnRpdGxlOiAiUG9kYXJjaXMgcHJvamVjdCBzdW1tYXJ5IHJlcG9ydCIKYXV0aG9yOiAiTWFyaWEgTm92b3NvbG92IgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgdGhlbWU6IHVuaXRlZAogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBmb250OiBGaXJhQ29kZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGFwZSkKbGlicmFyeShwaHl0b29scykKbGlicmFyeShndG9vbHMpCm5ub3JtIDwtIGZ1bmN0aW9uKHgpIHgvc3VtKHgpCnNvdXJjZShoZXJlOjpoZXJlKCJzY3JpcHRzL3Bsb3RfcmVhbFNGU19mdW5jdGlvbi5SIikpCnNvdXJjZShoZXJlOjpoZXJlKCJzY3JpcHRzL3Bsb3RfUENBbmdzZF9mdW5jdGlvbi5SIikpCnNvdXJjZShoZXJlOjpoZXJlKCJzY3JpcHRzL0V2b1RyZWVfaWJzTWF0X2Z1bmN0aW9uLlIiKSkKc291cmNlKGhlcmU6OmhlcmUoInNjcmlwdHMvZnN0X3BlYWtfc2VhcmNoX3Jhc211c0FsZ29fZnVuY3Rpb24uUiIpKQpzb3VyY2UoaGVyZTo6aGVyZSgic2NyaXB0cy9yZWFkX2FiYmFfYmFiYV9kYXRhX2Z1bmN0aW9uLlIiKSkKc291cmNlKGhlcmU6OmhlcmUoInNjcmlwdHMvZ2V0RHN0YXQzcG9wX2Z1bmN0aW9uLlIiKSkKcG9wX2RhdGE8LSByZWFkX2NzdihoZXJlOjpoZXJlKCJkYXRhL3BvcF9kYXRhX3dpdGhfYmFtTmFtZXMuY3N2IiksY29sX3NlbGVjdCA9IC0xKQpjb2xzLnBzIDwtIGMoIiNFNjlGMDAiLCAiIzU2QjRFOSIsIiMxMzZkMTUiKQpwb3BfZGF0YTI8LSByZWFkX2NzdihoZXJlOjpoZXJlKCJkYXRhL3BvcF9kYXRhX3dpdGhfYmFtTmFtZXMuY3N2IiksY29sX3NlbGVjdCA9IC0xKSAlPiUgCiAgc2VsZWN0KG5naV9pZCxpc2xhbmQpCgpwb3BfZGF0YTI8LSByYmluZChwb3BfZGF0YTIsYygiU1JSMTQwMDkzOTlfMSIsIlBtZWxpcyIpKQpgYGAKCiMgUHJvamVjdCBzdW1tYXJ5CgpJbiAxOTcxIGEgcmVjaXByb2NhbCBpbnRyb2R1Y3Rpb24gd2FzIGRvbmUgYmV0d2VlbiBQb2QgS29waXN0ZSBpc2xhbmQgYW5kIFBvZCBNcmNhcnUgaXNsYW5kIGluIHRoZSB0aGUgU291dGggQWRyaWF0aWMgU2VhLiBUZW4gaW5kaXZpZHVhbHMgb2YgKlBvZGFyY2lzIHNpY3VsdXMqIHdlcmUgcmVsb2NhdGVkIGZyb20gUG9kIEtvcGlzdGUgdG8gUG9kIE1yY2FydSwgYW5kIDEwIGluZGl2aWR1YWxzIG9mICpQb2RhcmNpcyBtZWxpc2VsbGVuc2lzKiB3ZXJlIHJlbG9jYXRlZCBmcm9tIFBvZCBNcmNhcnUgdG8gUG9kIEtvcGlzdGUuIEJvdGggaXNsYW5kcyB3ZXJlIGluaGliaXRlZCBvbmx5IGJ5IHRoZSBzb3VyY2Ugc3BlY2llcyBhdCB0aGUgdGltZSAtICpQLiBzaWN1bHVzKiBvbiBQb2QgS29waXN0ZSBhbmQgKlAuIG1lbGlzZWxsZW5zaXMqIG9uIFBvZCBNcmNhcnUuCgpBZnRlciB+MzUgeWVhcnMgcmVzZWFyY2hlcnMgY2FtZSBiYWNrIHRvIHRoZSBpc2xhbmRzIGFuZCB3aXRuZXNzZWQgZHJhc3RpYyBtb3JwaG9sb2dpY2FsIGNoYW5nZXMgYmV0d2VlbiAqUC4gc2ljdWx1cyogb24gUG9kIEtvcGlzdGUsIGFuZCAqUC4gc2ljdWx1cyogb24gUG9kIE1yY2FydS4gClRvIGxpbmsgdGhlIGdlbm9taWNzIHdpdGggdGhlIHBoZW5vdHlwaWMgb2JzZXJ2YXRpb24gd2Ugc2VxdWVuY2VkIDQ3IGluZGl2aWR1YWxzIG9mICpQLiBzaWN1bHVzKiBmcm9tIGVhY2ggaXNsYW5kLgpUaGlzIHJlcG9ydCBwcmVzZW50cyB0aGUgc2VxdWVuY2UgY292ZXJhZ2UgZm9yIHRoZSB3aG9sZSBnZW5vbWUgYW5kIHRoZSBtaXRvR2Vub21lLCBhbmQgYmFzaWMgZXhwbG9yYXRvcnkgYW5hbHlzZXMuCgpJbiBhbGwgdGhlIHBsb3RzICoqSyoqIChPcmFuZ2UpIHJlcHJlc2VudHMgdGhlIFBvZCBLb3Bpc3RlIHBvcHVsYXRpb24gKHRoZSBzb3VyY2UpIGFuZCAqKk0qKiAoQmx1ZSkgcmVwcmVzZW50cyB0byBQb2QgTXJjYXJ1IHBvcHVsYXRpb24gKHRoZSByZWxvY2F0ZWQgcG9wdWxhdGlvbikuCgojIERhdGEgc3VtbWFyeQoKIyMgRGF0YSBxdWFsaXR5CgojIyMgQ292ZXJhZ2UKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkNvdjwtIHJlYWRfY3N2KGhlcmU6OmhlcmUoImRhdGEvY292ZXJhZ2Vfc3VtbWFyeV8xMzAxMjAuY3N2IikpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHNhbXBsZV9uYW1lKSkgJT4lIAogIG11dGF0ZShyZWFsX3NhbXBsZSA9IGZjdF9pbm9yZGVyKHJlYWxfc2FtcGxlKSkKZ2dwbG90KENvdixhZXMocmVhbF9zYW1wbGUsbWVhbl9jb3ZlcmFnZSxmaWxsPWlzbGFuZCkpKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNFNjlGMDAiLCAiIzU2QjRFOSIpKSsKICB0aGVtZV9idygpKwogIHRoZW1lKGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCwgdmp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlPSJib2xkIiksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpKwogIGxhYnMoeSA9ICJDb3ZlcmFnZSAoWCkiLCB4ID0gInNhbXBsZSIsZmlsbCA9ICJTYW1wbGUgSXNsYW5kOiIpCmBgYAoKIyMjIEVycm9yIHJhdGUgCgohW10oL1VzZXJzL3JsdzM2My9Ecm9wYm94L01hcmlhIFJlc2VhcmNoL0NvbGxhYm9yYXRpb25zL1AuIHNpY3VsdXMgZ2Vub21pY3MgKEEuIEhlcnJlbCwgQW5hbWFya2EsIE1vcnRlbiwgUmFzbXVzKS9Qb2RhcmNpc19zaWN1bHVzX21hcHBpbmcvcGxvdHMvZXJyb3JfcmF0ZV9QU19yZWZfMTkwNTIxX3Bsb3RzT3ZlcmFsbC5wbmcpCgoKIyMjIExEIGRlY2F5CgpgYGB7ciBmaWcuYWxpZ249ImNlbnRlciIsIGZpZy53aWR0aD0yMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgicGxvdHMvcGxvdF9wb3BLX3BvcE1fbmdzTEQucGRmIiksZHBpID0gMzAwKQpgYGAKCiMjIFNGUyBwbG90cwpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFyKG1mcm93PWMoMSwyKSkKcF9yZWFsU0ZTKGRhdGFfcGF0aCA9ICJkYXRhL2FuZ3NkL3BvcEtfTm9JbnRyb2dyZXNfbm9SZWxhdGVkX0xhcmdlU2NhZl9ub1NleF93aXRoRGVwdGhfMTUwOTIxLnNhZi5zZnMiLHBvcF9uYW1lID0gIlBvcEsiLG1haW4gPSAiUG9wSyBub0ludHJvZ3Jlc3NlZCBpbmRpdmlkdWFscyIpCgpwX3JlYWxTRlMoZGF0YV9wYXRoID0gImRhdGEvYW5nc2QvcG9wTV9Ob0ludG9yZ3Jlc19MYXJnZVNjYWZfbm9TZXhfd2l0aGhEZXB0aF8xNTA5MjEuc2FmLnNmcyIscG9wX25hbWUgPSAiUG9wTSIsbWFpbiA9ICJQb3BNIG5vSW50cm9ncmVzc2VkIGluZGl2aWR1YWxzIikKYGBgCgojIFBDQQoKYGBge3IgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KUENBbmdzZF9wcm9wX3RhYmxlKGRhdGFfcGF0aCA9ICJkYXRhL1BDQV9BbGxfc25wUHZhbF9MYXJnZVNjYWZfbm9TZXhfYmVhZ2xlX3dpdGhEZXB0aF8xOTAzMjEuY292IikKCnBjYS5taW5tYWY8LSBwbG90X1BDQW5nc2QoZGF0YV9maWxlID0gImRhdGEvUENBX0FsbF9zbnBQdmFsX0xhcmdlU2NhZl9ub1NleF9iZWFnbGVfd2l0aERlcHRoXzE5MDMyMS5jb3YiLHZhcl9kYXRhID0gcG9wX2RhdGEsdmFyX25hbWVzID0gYygidXNlcl9pZCIsImlzbGFuZCIpLHBsb3RfY29scyA9IGNvbHMucHMscGNfdG9fcGxvdCA9IGMoIlBDMSIsIlBDMiIpKSsKICB4bGFiKCJQQzEgKDUuNiUpIikrCiAgeWxhYigiUEMyICgxLjMlKSIpCnBjYS5taW5tYWYrCiAgZ2VvbV9wb2ludChzaXplID0gNCkKcGxvdGx5OjpnZ3Bsb3RseShwY2EubWlubWFmKQojIyNwZGYoInBsb3RzL3BjYV9yZXNfbmV3LnBkZiIpCiMjI3BjYS5taW5tYWYrCiMjIyAgZ2VvbV9wb2ludChzaXplID0gNCkKIyMjZGV2Lm9mZigpCmBgYAoKIyBJQlMgdHJlZSAKCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD02LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90X2lic1RyZWUoZGF0YV9maWxlID0gImRhdGEvaWJzX0FsbF9zbnBQdmFsX0xhcmdlU2NhZl9ub1NleF93aXRoRGVwdGhfMTkwMzIxLmlic01hdCIsY29sLm5hbSA9IHBvcF9kYXRhJHVzZXJfaWQsY29sb3IgPSBjb2xzLnBzLHBvcC5kYXRhID0gcG9wX2RhdGEscm9vdCA9IFQpCmBgYAoKIyBSZWxhdGVkbmVzcwoKIyMgUG9wSwpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbmdzUl9wb3BLX2RhdGE8LSByZWFkX2RlbGltKGhlcmU6OmhlcmUoImRhdGEvcmVzX25nc1JlbGF0ZV9wb3BLX21pbm1hZl8xMDBLX25vU2V4XzIxMDMyMSIpLGRlbGltID0gIlx0IikgJT4lIAogIGphbml0b3I6OmNsZWFuX25hbWVzKCkKCnBvcEtfZGF0YTwtIHBvcF9kYXRhICU+JQogIGZpbHRlcihpc2xhbmQ9PSJLIikgJT4lIAogIHNlbGVjdCh1c2VyX2lkKSAlPiUgCiAgbXV0YXRlKHNlcV9uYW1lID0gc2VxKDAsNDUpKQoKbmdzUmVsYXRlLnBvcEs8LSAgbmdzUl9wb3BLX2RhdGEgJT4lIAogIGxlZnRfam9pbihwb3BLX2RhdGEsYnk9YygiYSI9InNlcV9uYW1lIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKGluZDE9dXNlcl9pZCkgJT4lCiAgbGVmdF9qb2luKHBvcEtfZGF0YSxieT1jKCJiIj0ic2VxX25hbWUiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoaW5kMj11c2VyX2lkKSAlPiUgCiAgcmVsb2NhdGUoaW5kMSxpbmQyKQoKaW5icmVkRjI8LSBuZ3NSZWxhdGUucG9wSyAlPiUgCiAgc2VsZWN0KGEsYixpbmQxLGluZDIscmFiKSAlPiUgCiAgbXV0YXRlKGluZDE9bmF0dXJhbHNvcnQ6Om5hdHVyYWxmYWN0b3IoaW5kMSkpICU+JSAKICBtdXRhdGUoaW5kMj1uYXR1cmFsc29ydDo6bmF0dXJhbGZhY3RvcihpbmQyKSkgJT4lIAogIG11dGF0ZShwYWlyID0gcGFzdGUoaW5kMSxpbmQyLHNlcD0iXyIpKSAKCm5ncy5wNDwtIGdncGxvdChpbmJyZWRGMixhZXMoaW5kMSxpbmQyLGZpbGw9IHJhYixsYWJlbCA9IHBhaXIpKSsKICBnZW9tX3RpbGUoKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICIiKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKcGxvdGx5OjpnZ3Bsb3RseShuZ3MucDQpCmBgYAoKIyMgUG9wTQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbmdzUl9wb3BNX2RhdGE8LSByZWFkX2RlbGltKGhlcmU6OmhlcmUoImRhdGEvcmVzX25nc1JlbGF0ZV9wb3BNX21pbm1hZl8xMDBLX25vU2V4XzIxMDMyMSIpLGRlbGltID0gIlx0IikgJT4lIAogIGphbml0b3I6OmNsZWFuX25hbWVzKCkKCnBvcE1fZGF0YTwtIHBvcF9kYXRhICU+JQogIGZpbHRlcihpc2xhbmQ9PSJNIikgJT4lIAogIHNlbGVjdCh1c2VyX2lkKSAlPiUgCiAgbXV0YXRlKHNlcV9uYW1lID0gc2VxKDAsNDcpKQoKbmdzUmVsYXRlLnBvcE08LSAgbmdzUl9wb3BNX2RhdGEgJT4lIAogIGxlZnRfam9pbihwb3BNX2RhdGEsYnk9YygiYSI9InNlcV9uYW1lIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKGluZDE9dXNlcl9pZCkgJT4lCiAgbGVmdF9qb2luKHBvcE1fZGF0YSxieT1jKCJiIj0ic2VxX25hbWUiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoaW5kMj11c2VyX2lkKSAlPiUgCiAgcmVsb2NhdGUoaW5kMSxpbmQyKQoKaW5icmVkX3BvcE1fRjI8LSBuZ3NSZWxhdGUucG9wTSAlPiUgCiAgc2VsZWN0KGEsYixpbmQxLGluZDIscmFiKSAlPiUgCiAgbXV0YXRlKGluZDE9bmF0dXJhbHNvcnQ6Om5hdHVyYWxmYWN0b3IoaW5kMSkpICU+JSAKICBtdXRhdGUoaW5kMj1uYXR1cmFsc29ydDo6bmF0dXJhbGZhY3RvcihpbmQyKSkgJT4lIAogIG11dGF0ZShwYWlyID0gcGFzdGUoaW5kMSxpbmQyLHNlcD0iXyIpKSAKCm5ncy5wNC5wb3BNPC0gZ2dwbG90KGluYnJlZF9wb3BNX0YyLGFlcyhpbmQxLGluZDIsZmlsbD0gcmFiLGxhYmVsID0gcGFpcikpKwogIGdlb21fdGlsZSgpKwogIHRoZW1lX21pbmltYWwoKSsKICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhuYW1lID0gIiIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpwbG90bHk6OmdncGxvdGx5KG5ncy5wNC5wb3BNKQpgYGAKCgpUaGUgYW5hbHlzZXMgZm91bmQgdGhlIGZvbGxvd2luZyBpbmRpdmlkdWFscyBhcyByZWxhdGVkIChpbmRpdmlkdWFscyBpbiBib2xkIHdlcmUgcmVtb3ZlZCBmcm9tIGludHJvZ3Jlc3Npb24gYW5hbHlzZXMpOgoKICoqSzMqKiAtIEszNQoKICoqSzMqKiAtIEs0MQoKICoqSzE4KiogLSBLNDUKCiBLNyAtICoqSzM5KioKCiAqKksyNCoqIC0gSzI5CgoKIyBBZG1peHR1cmUKCldlIHJhbiBhZG1peHR1cmUgdXNpbmcgTkdTQWRtaXggdG8gYW5hbHlzZSBob3cgbWFueSBjbHVzdGVycyBjYW4gYmUgc2VlbiBhbW9uZyB0aGUgdHdvIHBvcHVsYXRpb25zLCBleGNsdWRpbmcgdGhlIHJlbGF0ZWQgaW5kaXZpZHVhbHMgZnJvbSBQb3BLLiBQcmVzZW50ZWQgaGVyZSBhcmUgcmVzdWx0cyBmb3IgSz0yLCBLPTMgYW5kIEs9NC4gVGhlcmUgaXMgbm8gcXVhbnRpdGF0aXZlIG1ldGhvZCBvZiBjaG9vc2luZyB0aGUgY29ycmVjdCBLLiBIb3dldmVyLCBLPTIgc2hvd3MgYSBjbGVhciBkaXZpc3Npb24gYmV0d2VlbiB0aGUgdHdvIHBvcHVsYXRpb25zLiBLPTMgYWRkcyBhbm90aGVyIGFkbWl4dHVyZSAoZ3JlZW4pIHdoaWNoIG1pZ2h0IHJlcHJlc2VudCAqUC4gbWVsaXNlbGxlbnNpcyosIGhvd2V2ZXIsIGl0IGRvZXMgbm90IGFsaWduIHdpdGggdGhlIHJlc3VsdHMgZnJvbSBBQkJBLUJBQkEgKHNlZSBiZWxsb3cpLgoKCmBgYHtyIGZpZy5hbGlnbj0iY2VudGVyIiwgZmlnLndpZHRoPTIyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJwbG90cy9wb25nX2syXzRfYWRtaXgucG5nIiksZHBpID0gMzAwKQpgYGAKCiMgQUJCQS1CQUJBCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpQU19QbWVsaXNfcmVmPC0gcmVhZF9kZWxpbShoZXJlOjpoZXJlKCJkYXRhL2FiYmFiYWJhX3dpdGhfUG1saXNfb3JpZ19qYWtuaWYudHh0IiksZGVsaW09Ilx0Iixjb2xfc2VsZWN0ID0gLTEwKSAlPiUgCiAgI3VwZGF0ZSB0aGUgbmFtZXMgdG8gZml0IHRoZSBuYW1lcyBpbiB0aGUgcG9wZGF0YSBmaWxlCiAgbXV0YXRlKEgxID0gc3RyX2V4dHJhY3QoSDEsIlteX10qX1teX10qIiksSDIgPSBzdHJfZXh0cmFjdChIMiwiW15fXSpfW15fXSoiKSxIMyA9IHN0cl9leHRyYWN0KEgzLCJbXl9dKl9bXl9dKiIpKQojY3JlYXRlIGEgdmVjdG9yIHRoYXQgaG9sZHMgdGhlIGlzbGFuZHMKbG9jSWR4X1BTPC0gcG9wX2RhdGEyJGlzbGFuZAojbmFtZSBpdCB3aXRoIHRoZSBpbmQgbmFtZXMgdGhhdCBmaXQgdGhlIGFiYmFiYWJhIGRhdGEKbmFtZXMobG9jSWR4X1BTKTwtIHBvcF9kYXRhMiRuZ2lfaWQKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI2NyZWF0ZSBhIG1hdHJpeCB0aGF0IHdlIHdpbGwgdXNlIHRvIGdlbmVyYXRlIGRhdGEgZm9yIHBvcEsgd2l0aCBwb3BNIGFzIGFuIG91dGdyb3VwIGluIGdyb3VwCmdyb3VwX3BvcEs8LSBtYXRyaXgoYyhyZXAoIksiLDIpLCAiUG1lbGlzIiksbmNvbD0zLCBieXJvdz1UKQoKI3J1biB0aGUgZnVuY3Rpb24gdGhhdCByZW5hbWVzIGFsbCB0aGUgZmlsZSBhbmQga2VlcCBvbmx5IHRoZSByb3dzIHRoYXQgZml0IHRoZSBmaXhlZCBncm91cCBzZXR0aW5nCmRzdGF0Rml4SDFIMlBvcEtDaGFuZ2VIMyA8LSBkby5jYWxsKHJiaW5kLGFwcGx5KGdyb3VwX3BvcEssIDEsIGdldERzdGF0M3BvcCwgZHN0YXRkZj1QU19QbWVsaXNfcmVmLGxvY0lkeCA9IGxvY0lkeF9QUykpCmxlZ19zY2FsZV9wb3BLPC1tYXgoYyhhYnMobWluKGRzdGF0Rml4SDFIMlBvcEtDaGFuZ2VIMyRaKSksYWJzKG1heChkc3RhdEZpeEgxSDJQb3BLQ2hhbmdlSDMkWikpKSkKCnBsb3QuUEtQSzwtIHBsb3QuZGF0YS5zYW1lLnBvcChkc3RhdEZpeEgxSDJQb3BLQ2hhbmdlSDMsdGl0bGUgPSAiUG9wSyBIMSwgUG9wSyBIMiwgUG1lbGlzIEgzLCBQbXVyIEg0LCBQUyByZWYiKQpwbG90bHk6OmdncGxvdGx5KHBsb3QuUEtQSykKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI2NyZWF0ZSB0aGUgc2FtZSBmb3IgcG9wTQpncm91cF9wb3BNPC0gbWF0cml4KGMocmVwKCJNIiwyKSwgIlBtZWxpcyIpLG5jb2w9MywgYnlyb3c9VCkKI2RvIHRoZSBzYW1lIGZvciBwb3BNIGFzIGEgc2V0IGdyb3VwCmRzdGF0Rml4SDFIMlBvcE1DaGFuZ2VIMyA8LSBkby5jYWxsKHJiaW5kLGFwcGx5KGdyb3VwX3BvcE0sIDEsIGdldERzdGF0M3BvcCwgZHN0YXRkZj1QU19QbWVsaXNfcmVmLGxvY0lkeCA9IGxvY0lkeF9QUykpCmxlZ19zY2FsZV9wb3BNPC1tYXgoYyhhYnMobWluKGRzdGF0Rml4SDFIMlBvcE1DaGFuZ2VIMyRaKSksYWJzKG1heChkc3RhdEZpeEgxSDJQb3BNQ2hhbmdlSDMkWikpKSkKCnBsb3QuUE1QTTwtIHBsb3QuZGF0YShkc3RhdEZpeEgxSDJQb3BNQ2hhbmdlSDMsdGl0bGUgPSAiUG9wTSBIMSwgUG9wTSBIMiwgUG1lbGlzIEgzLCBQbXVyIEg0LCBQUyByZWYiKQpwbG90bHk6OmdncGxvdGx5KHBsb3QuUE1QTSkKYGBgCgoKIyMgQmV0d2VlbiBwb3B1bGF0aW9uIEYqc3QqCgpUaGUgRipzdCogdmFsdWUgYmV0d2VlbiB0aGUgdHdvIHBvcHVsYXRpb25zIGlzICoqMC4wMzQ0NzUqKgoKIyBGc3Qgc2NhbnMKCiMjIE1hbmhhdHRhbiBwbG90CgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZnN0X2FuZ3NkPC0gcmVhZF9kZWxpbShoZXJlOjpoZXJlKCJkYXRhL3BvcEtfcG9wTV9zbGlkaW5nV2luZG93X2ZzdF9MYXJnZVNjYWZfbm9NNDhfbm93aGljaGZzdF8wNzEyMjEiKSxkZWxpbSA9ICJcdCIsY29sX25hbWVzID0gRixza2lwID0gMSxjb2xfc2VsZWN0ID0gLTEpICU+JSAKICBkcGx5cjo6cmVuYW1lKGNociA9IFgyLG1pZHBvaW50ID0gWDMsIG5zaXRlcyA9IFg0LFBLX1BNX2ZzdCA9IFg1KSAlPiUgCiAgbXV0YXRlKGN1bV9taWQgPSBjdW1zdW0obWlkcG9pbnQpKQojIGNhbGN1bGF0ZSB0aGUgdGhyZXNob2xkIGZvciBvdXRsaWVycyBhbmQgdGhlIG91dGxpZXJzCm15X3RocmVzaG9sZC51dyA8LSBxdWFudGlsZShmc3RfYW5nc2QkUEtfUE1fZnN0LCAwLjk5NSwgbmEucm0gPSBUKQoKZnN0X2FuZ3NkX291dGxpZXI8LSBmc3RfYW5nc2QgJT4lIAogIG11dGF0ZShvdXRsaWVyLnV3ID0gaWZlbHNlKFBLX1BNX2ZzdCA+IG15X3RocmVzaG9sZC51dywgIm91dGxpZXIiLCAiYmFja2dyb3VuZCIpKQoKb3V0bGllcl90YWJsZTwtIGZzdF9hbmdzZF9vdXRsaWVyICU+JSAKICBncm91cF9ieShvdXRsaWVyLnV3KSAlPiUgCiAgdGFsbHkoKQoKa25pdHI6OmthYmxlKG91dGxpZXJfdGFibGUsYWxpZ24gPSAnYycpCiMgb3V0bGllciBwbG90CmdncGxvdChmc3RfYW5nc2Rfb3V0bGllcixhZXMoY3VtX21pZC8xMDAwMDAwMCxQS19QTV9mc3QsY29sb3IgPSBvdXRsaWVyLnV3KSkrCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDAwMDAwIiwiI0U0NTcyRSIpKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBteV90aHJlc2hvbGQudXcsbHR5ID0gMikrCiAgeGxhYigiR2JwIikrCiAgeWxhYigiRnN0IikKYGBgCgojIyBGc3QgcGVha3MKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNoci5kYXRhPC0gcmVhZF9kZWxpbShoZXJlOjpoZXJlKCJkYXRhL2Fib3ZlXzEwMGtiX25vU2V4X3NjYWZmX2xpc3QuY3N2IiksZGVsaW0gPSAiLCIpIAoKZnN0X2hpZ2g8LSBmc3RfYW5nc2Rfb3V0bGllciRQS19QTV9mc3QKCnRydWVfcGVhazwtIGZzdF9wZWFrcyhmc3RfaGlnaCxsaW1pdHMgPSBjKDAuMjYsMC4yMSkpCgprbml0cjo6a2FibGUoZnN0X2FuZ3NkX291dGxpZXIgJT4lIAogIG11dGF0ZShwZWFrID0gY2FzZV93aGVuKFBLX1BNX2ZzdCVpbiV0cnVlX3BlYWskZnN0X3ZhbH4icGVhayIsVFJVRX4ibm90X3BlYWsiKSkgJT4lIAogIGdyb3VwX2J5KHBlYWspICU+JSAKICB0YWxseSgpKQoKZnN0X3BlYWtfcGxvdDwtIGZzdF9hbmdzZF9vdXRsaWVyICU+JSAKICBtdXRhdGUocGVhayA9IGNhc2Vfd2hlbihQS19QTV9mc3QlaW4ldHJ1ZV9wZWFrJGZzdF92YWx+InBlYWsiLFRSVUV+Im5vdF9wZWFrIikpICU+JSAKICBnZ3Bsb3QoYWVzKGN1bV9taWQvMTAwMDAwMDAsUEtfUE1fZnN0LGNvbG9yID0gcGVhayxzaXplID0gcGVhaykpKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSsKICB0aGVtZV9taW5pbWFsKCkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzAwMDAwMCIsIiM5NjAyMDIiKSkrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbXlfdGhyZXNob2xkLnV3LGx0eSA9IDIpKwogIHhsYWIoIkdicCIpKwogIHlsYWIoIkZzdCIpCgojIyMjanBlZygicGxvdHMvZnN0X3BlYWtzX3Bsb3QyLmpwZWciLHdpZHRoID0gNDAsaGVpZ2h0ID0gMzAscmVzID0gMjAwKQojIyMjZnN0X3BlYWtfcGxvdAojIyMjZGV2Lm9mZigpCmBgYAoKIyBCTEFTVCByZXN1bHRzCgpIZXJlIGFyZSB0aGUgdGhyZWUgbG9jYWxpdGllcyB3aXRoIHRoZSBoaWdoZXN0IEZzdCBiZXR3ZWVuIHRoZSBwb3B1bGF0aW9ucyB3aXRoIHRoZSBnZW5lcyB0aGF0IGFyZWEgY29kZXMgZm9yIGFuZCB3aGF0IHRoaXMgZ2VuZSBtaWdodCBiZSByZWxhdGVkIHRvLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Ka25pdHI6OmthYmxlKHJlYWRfY3N2KGhlcmU6OmhlcmUoImRhdGEvZm9yUl9wZWFrc19mc3Rfb3V0bGllcnNfUk5fTWV0aG9kXzA5MTIyMV8yLmNzdiIpKSAlPiUgCiAgc2xpY2UoMTozKSAlPiUgCiAgc2VsZWN0KDQsMTAsMTEsMTIsMTMpICU+JSAKICAgIHJlbmFtZSh0cmFuc19pZCA9IGxpZnRlZF9jbGVhbi5nZmZfcmVzKSkKYGBgCgojIERlbW9ncmFwaGljIG1vZGVsaW5nCgpUaGUgbW9kZWwgdGhhdCB3ZSBmb2N1c2VkIG9uIGFzc3VtZXMgdGhhdCB0aGVyZSBpcyBzb21lIGludHJvZ3Jlc3Npb24gZnJvbSBhIGdob3N0IHBvcHVsYXRpb24gaW4gYm90aCBvZiB0aGUgcG9wdWxhdGlvbnMgdGhhdCBoYXBwZW5lZCBhZnRlciB0aGUgYm90dGxlbmVjay4gVGhpcyBpcyB0aGUgbW9kZWwgd2UgdXNlZDoKCiFbXSgvVXNlcnMvcmx3MzYzL0Ryb3Bib3gvTWFyaWEgUmVzZWFyY2gvQ29sbGFib3JhdGlvbnMvUC4gc2ljdWx1cyBnZW5vbWljcyAoQS4gSGVycmVsLCBBbmFtYXJrYSwgTW9ydGVuLCBSYXNtdXMpL1BvZGFyY2lzX3NpY3VsdXNfbWFwcGluZy9wbG90cy9EZW1vZ3JhcGhpY19tb2RlbC5wbmcpCgpUaGUgaWRlYSB3YXMgdG8gY2FsY3VsYXRlIHRoZSBtaWdyYXRpb24gYW5kIHBvcHVsYXRpb24gdmFsdWVzIHRoYXQgYXJlIGNsb3Nlc3QgdG8gdGhlIHJlYWxpdHkgYXMgd2Uga25vdyBpdCBhbmQgbGV0IHRoZSBvcHRpbWl6YXRpb24gdG8gYWRqdXN0IHRoZSB2YWx1ZXMgdG8gZ2V0IHRoZSBtb3N0IGxpa2VseSBtb2RlbC4KCldlIGNoZWNrZWQgd2hldGhlciB0aGUgbW9kZWwgZ2l2ZXMgYSBnb29kIGVzdGltYXRpb24gYnkgY29tcGFyaW5nIHRoZSB0cnVlIEYqc3QqIHZhbHVlcyB3aXRoIHRoZSBtb2RlbGVkIEYqc3QqIHZhbHVlcy4gVGhpcyBpcyB3aGF0IHdlIGdvdDoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmRmLmZzdDwtIGFzLmRhdGEuZnJhbWUobWF0cml4KGRhdGEgPSBOQSxuY29sID0gNCxucm93ID0gMykpCnJvdy5uPC0gYygib2JzZXJ2ZWQiLCJtb2RlbGxlZF9DMTAwIiwibW9kZWxsZWRfQzEwIikKbmFtZXMoZGYuZnN0KTwtIGMoIlgxIiwiRnN0U1MiLCJGc3RXIiwiRnN0VSIpCmRmLmZzdCRYMTwtIHJvdy5uCgpzb3VyY2UoaGVyZTo6aGVyZSgic2NyaXB0cy9mdW5jdGlvbnNfZm9yX2ZzdF9mcm9tXzJkU0ZTLlIiKSkKIyMjIyMgTW9kZWwgRnN0IEMxMDAgIyMjIyMjIwpmdWxsPC1zY2FuKGhlcmU6OmhlcmUoImRhdGEvbW9kZWw5OF9NU0ZTLnR4dCIpLHNraXAgPSAyKQpmdWxsTTwtbWF0cml4KGZ1bGwsIG5jb2w9OTUsIG5yb3c9ODUsIGJ5cm93PVQpCmZ1bGxNWzE6NSwxOjVdCm9yZy5mc3QubW9kZWw8LSBnZXRGc3QoZnVsbE0pCmRmLmZzdFsyLDJdPC0gb3JnLmZzdC5tb2RlbApyZXkuZnN0PC0gZ2V0UmV5bm9sZHNGc3QoZnVsbE0pCnN0cihyZXkuZnN0KQpkZi5mc3RbMiwzXTwtIHJleS5mc3RbWzFdXQpkZi5mc3RbMiw0XTwtIHJleS5mc3RbWzJdXQoKIyMjIyMgTW9kZWwgRnN0IEMxMCAjIyMjIwpmdWxsPC1zY2FuKGhlcmU6OmhlcmUoImRhdGEvbW9kZWw5OV9NU0ZTLnR4dCIpLHNraXAgPSAyKQpmdWxsTTwtbWF0cml4KGZ1bGwsIG5jb2w9OTUsIG5yb3c9ODUsIGJ5cm93PVQpCmZ1bGxNWzE6NSwxOjVdCm9yZy5mc3QubW9kZWw8LSBnZXRGc3QoZnVsbE0pCmRmLmZzdFszLDJdPC0gb3JnLmZzdC5tb2RlbApyZXkuZnN0PC0gZ2V0UmV5bm9sZHNGc3QoZnVsbE0pCnN0cihyZXkuZnN0KQpkZi5mc3RbMywzXTwtIHJleS5mc3RbWzFdXQpkZi5mc3RbMyw0XTwtIHJleS5mc3RbWzJdXQoKIyMjIyMgVHJ1ZSBGc3QgIyMjIyMKdHJ1ZS5kYXRhPC0gc2NhbihoZXJlOjpoZXJlKCJkYXRhL3BvcEsucG9wTV8yZHNmc19MYXJnZVNjYWZfbm9SZWxhdGVUUlVFX25vTTQ4XzIzMDIyMi5tbCIpKQp0cnVlLmRhdGEubTwtIG1hdHJpeCh0cnVlLmRhdGEsIG5jb2w9OTUsIG5yb3c9ODUsIGJ5cm93PVQpCnRydWUuZGF0YS5tWzE6NSwxOjVdCnRydWUuZGF0YS51bmZsYXQ8LSB1bmZsYXRlbl9tYXRyaXgodHJ1ZS5kYXRhLGRpbXMgPSBjKDk1LDg1KSkKdHJ1ZS5kYXRhLnVuZmxhdFsxOjUsMTo1XQoKb2JzLmZzdC5vcmc8LSBnZXRGc3QodHJ1ZS5kYXRhLm0pCmdldEZzdCh0cnVlLmRhdGEudW5mbGF0KQoKcmV5LmZzdC5vYnM8LSBnZXRSZXlub2xkc0ZzdCh0cnVlLmRhdGEubSkKCmRmLmZzdFsxLDJdPC0gb2JzLmZzdC5vcmcKZGYuZnN0WzEsM108LSByZXkuZnN0Lm9ic1tbMV1dCmRmLmZzdFsxLDRdPC0gcmV5LmZzdC5vYnNbWzJdXQoKYGBgCgpgYGB7cn0Ka25pdHI6OmthYmxlKGRmLmZzdCkKYGBgCgoKVGhlIG5ldyB2YWx1ZXMgd2VyZSB0aGVuIHVzZWQgdG8gZ2VuZXJhdGUgU05QcyBmcm9tIDEwMCwwMDBicCBzaW11bGF0ZWQgRE5BIGZyYWdtZW50cyBmb3IgZWFjaCBwb3B1bGF0aW9uLiBUaGVzZSBTTlBzIHdlcmUgdXNlZCB0byBjYWxjdWxhdGUgdGhlIDJkU0ZTLiBUaGlzIHdhcyByZXBlYXRlZCAxLDAwMCBhbmQgY29tcGFyZWQgdG8gdGhlIHRydWUgRipzdCogcGVhayB2YWx1ZXMgd2UgZm91bmQgaW4gdGhlIEYqc3QqIHNjYW4uIFRoaXMgcGFydCBpcyBnaXZpbmcgc29tZSB1bmV4cGVjdGVkIHJlc3VsdHMgYW5kIHdlIGFyZSBzdGlsbCBpbiB0aGUgcHJvY2VzcyBvZiB0cm91Ymxlc2hvb3RpbmcgdGhlIHByb2JsZW0uCgojIEZ1dHVyZSBwbGFuZXMKClRoZSBwbGFuZSBub3cgaXMgdG8gd3JpdGUgdGhlIE1TIHRoYXQgd2lsbCBmb2N1cyBvbiBvdXIgRnN0IHNjYW4gYmFzZWQgZ2VuZXRpYyBmaW5kaW5ncyBhbmQgdGhlIGludHJvZ3Jlc3Npb24uIE9uY2UgdGhhdCBpcyBkb25lLCB3ZSBwbGFuIHRvIHdvcmsgb24gdGhlIHZhcmlvdXMgbXVzZXVtIHNhbXBsZXMgdGhhdCB3ZSBoYXZlIHRvIHNlZSB0aGUgY2hhbmdlIGluIHRoZSBnZW5ldGljIGNvbXBvc2l0aW9uIG92ZXIgdGltZS4=